#include <iostream>
#include <set>
#include <cstdio>
#include <fstream>
#include "log.hpp"
const static std::string sign = " ";
class Command
{
private:
    void load_safe_command(const std::string &set) // 将安全指令集从磁盘中装入内存中
    {
        std::ifstream in(set); // 打开我文件set
        if (!in.is_open())
        {
            LOG(FATAL, "open file error");
            return;
        }
        std::string line;
        while (std::getline(in, line))
        {
            LOG(FATAL, "load command [%s] success!\n", line.c_str());
            _safe_cmd.insert(line);
        }
        in.close(); // 关闭文件
    }

public:
    Command(const std::string cond_path)
        : _cond_path(cond_path)
    {
        load_safe_command(_cond_path);
    }
    std::string get_head(const std::string &cmd) // ls -a -l 获取指令头部
    {
        if (cmd.empty())
            return std::string();
        auto index = cmd.find(sign);
        if (index == std::string::npos)
            return cmd;
        else
            return cmd.substr(0, index);
    }
    bool check_safe(const std::string &cmd) // 检查指令是否安全
    {
        std::string head = get_head(cmd); // 获取指令头部，如：ls -l -a 指令中 ls
        if (head.empty())
            return false;
        auto iter = _safe_cmd.find(head); // 在安全指令集中查找指令头部
        if (iter != _safe_cmd.end())
        {
            return true;
        }
        return false;
    }
    std::string excute(const std::string &cmd) // 回调函数，cmd ：server端接收的指令，
    {
        std::string result;
        if (check_safe(cmd)) // 检查指令是否安全，即是否在安全指令集中
        {
            FILE *fp = popen(cmd.c_str(), "r"); // popen()函数执行cmd指令，创建一个管道，通过这个管道可以读取命令的输出，
            // 执行完后，可以使用fread，fgets从fp指定的管道中读取数据，最后不用这个管道了，用pclose(fp)关闭
            if (fp == nullptr)
            {
                return "failed";
            }
            char buffer[1024];
            while (fgets(buffer, sizeof(buffer), fp) != NULL) // 读取执行结果，写入result中
            {
                result += buffer;
            }
            pclose(fp);
        }
        else
        {
            result = "坏人！\n";
        }
        return result;
    }

private:
    std::set<std::string> _safe_cmd; // 安全指令集
    std::string _cond_path;          // 安全指令存放的路径
};